module CPU(
        input clk,
        input rst
    );
    //111
    //wire for IF
    wire [31:0] nextPC,currentPC,instruction,pc4;
    //wire for ID
    wire [5:0] opcode,func;
    wire [4:0] shamt,rs,rt,rd;
    wire [15:0] immediate_16;
    wire [25:0] immediate_26;
    wire RegDst,RegWrite,ALUSrc_sign,ALUSrc_zero,MemWrite,MemRead,jump,jr,write31;
    wire [2:0] branch,load_select;
    wire [3:0] ALU_operation;
    wire [4:0] wr;
    wire [31:0] wd,read1,read2;
    //wire for EX
    wire [31:0]ALU_result;
    wire [31:0] a,b;
    wire branch_result;
    //wire for DM
    wire [31:0] mem;
    //wire for WB
    wire [31:0] load_result;

    //IF
    assign pc4=currentPC+4;
    PC pc(
           .clk(clk),
           .rst(rst),
           .nextPC(nextPC),
           .currentPC(currentPC)
       );
    IM im(
           .currentPC(currentPC),
           .instruction(instruction)
       );

    //ID
    Decoder decoder(
                .instruction(instruction),
                .opcode(opcode),
                .func(func),
                .rs(rs),
                .rt(rt),
                .rd(rd),
                .shamt(shamt),
                .immediate_16(immediate_16),
                .immediate_26(immediate_26)
            );

    Control control(
                .opcode(opcode),
                .func(func),
                .RegDst(RegDst),
                .RegWrite(RegWrite),
                .ALUSrc_sign(ALUSrc_sign),
                .ALUSrc_zero(ALUSrc_zero),
                .MemWrite(MemWrite),
                .MemRead(MemRead),
                .load_select(load_select),
                .branch(branch),
                .jump(jump),
                .ALU_operation(ALU_operation),
                .jr(jr),
                .write31(write31)
            );
    GRF grf(
            .clk(clk),
            .rst(rst),
            .RegWrite(RegWrite),
            .reg1(rs),
            .reg2(rt),
            .wr(wr),
            .wd(wd),
            .read1(read1),
            .read2(read2),
            .pc(currentPC)
        );
    //EX
    assign a=read1;
    assign b=(ALUSrc_zero==1)?{{16{1'b0}},immediate_16}:
           (ALUSrc_sign==1)?{{16{immediate_16[15]}},immediate_16}:
           read2;
    ALU alu(
            .a(a),
            .b(b),
            .shamt(shamt),
            .ALU_operation(ALU_operation),
            .ALU_result(ALU_result)
        );
    Branch_judge branch_judge(
                     .a(a),
                     .b(b),
                     .branch(branch),
                     .branch_result(branch_result)
                 );
    NPC npc(
            .pc4(pc4),
            .pc(currentPC),
            .rs(a),
            .immediate_16(immediate_16),
            .immediate_26(immediate_26),
            .jump(jump),
            .jr(jr),
            .branch(branch_result),
            .npc_result(nextPC)
        );
    //DM
    DM dm(
           .MemWrite(MemWrite),
           .MemRead(MemRead),
           .clk(clk),
           .rst(rst),
           .address(ALU_result),
           .data(read2),
           .mem(mem),
           .pc(currentPC)
       );
    //WB
    Load load(
             .load_select(load_select),
             .mem(mem),
             .ALU_result(ALU_result),
             .load_result(load_result)
         );
    assign wd=(write31==1'b1)?pc4:load_result;
    assign wr=(write31==1'b1)?5'b11111:
           (RegDst==1'b1)?rd:
           rt;
endmodule


